<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>zookeeper | 雁过留声</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="查看zookeeper启动日志 .&#x2F;zkServer.sh start-foreground 查看当前节点状态.&#x2F;zkServer.sh status 创建一个临时节点create -e &#x2F;person yang 创建一个持久顺序节点 create -s &#x2F;person yang ZooKeeper 是一个典型的分布式数据一致性解决方案，分布式应用程序可以基于ZooKeeper 实现诸如数据发布&#x2F;">
<meta property="og:type" content="article">
<meta property="og:title" content="zookeeper">
<meta property="og:url" content="http://yanglf007.gitee.io/blog/2020/07/06/zookeeper/index.html">
<meta property="og:site_name" content="雁过留声">
<meta property="og:description" content="查看zookeeper启动日志 .&#x2F;zkServer.sh start-foreground 查看当前节点状态.&#x2F;zkServer.sh status 创建一个临时节点create -e &#x2F;person yang 创建一个持久顺序节点 create -s &#x2F;person yang ZooKeeper 是一个典型的分布式数据一致性解决方案，分布式应用程序可以基于ZooKeeper 实现诸如数据发布&#x2F;">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2020-07-05T16:21:50.282Z">
<meta property="article:modified_time" content="2020-09-06T08:42:08.542Z">
<meta property="article:author" content="yanglf007">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/blog/atom.xml" title="雁过留声" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/blog/css/style.css">

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/blog/" id="logo">雁过留声</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/blog/">Home</a>
        
          <a class="main-nav-link" href="/blog/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/blog/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yanglf007.gitee.io/blog"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-zookeeper" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/06/zookeeper/" class="article-date">
  <time datetime="2020-07-05T16:21:50.282Z" itemprop="datePublished">2020-07-06</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      zookeeper
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>查看zookeeper启动日志<br> ./zkServer.sh start-foreground</p>
<p>查看当前节点状态<br>./zkServer.sh status</p>
<p>创建一个临时节点<br>create -e /person yang</p>
<p>创建一个持久顺序节点</p>
<p>create -s /person yang</p>
<p>ZooKeeper 是一个典型的分布式数据一致性解决方案，分布式应用程序可以基于<br>ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。</p>
<ol>
<li>zookeeper四种节点<br>持久化节点<br>持久化顺序节点<br>临时节点 临时节点在客户端会话结束后，就会自动删除<br>临时顺序节点 </li>
</ol>
<ol start="2">
<li><p>zookeeper应用场景<br>1、命名服务<br>2、配置管理<br>3、集群管理<br>4、分布式锁<br>5、队列管理</p>
</li>
<li><p>zookeeper如何选举leader</p>
</li>
<li><p>zookeeper为什么需要leader </p>
</li>
<li><p>zk原子广播机制原理<br>数据一致性的算法，即ZAB（ZooKeeper Atomic Broadcast ）</p>
</li>
</ol>
<p>消息机制保障：可靠传送（如果消息m被一台服务器送达，它最终会被送达到所有服务器），<br>顺序</p>
<p>Zookeeper的核心是原子广播，这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式，它们分别是恢复模式和广播模式。</p>
<p>　　　当服务启动或者在领导者崩溃后，Zab就进入了恢复模式，当领导者被选举出来，且大多数server的完成了和leader的状态同步以后，恢复模式就结束了。</p>
<p>　　　状态同步保证了leader和server具有相同的系统状态</p>
<p>　　» 一旦leader已经和多数的follower进行了状态同步后，他就可以开始广播消息了，即进入广播状态。这时候当一个server加入zookeeper服务中，它会在恢复模式下启动，</p>
<p>　　　发现leader，并和leader进行状态同步。待到同步结束，它也参与消息广播。Zookeeper服务一直维持在Broadcast状态，直到leader崩溃了或者leader失去了大部分</p>
<p>　　　的followers支持。</p>
<p>　　» 广播模式需要保证proposal被按顺序处理，因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。</p>
<p>　　　实现中zxid是一个64为的数字，它高32位是epoch用来标识leader关系是否改变，每次一个leader被选出来，它都会有一个新的epoch。低32位是个递增计数。</p>
<p>　　» 当leader崩溃或者leader失去大多数的follower，这时候zk进入恢复模式，恢复模式需要重新选举出一个新的leader，让所有的server都恢复到一个正确的状态。　</p>
<p>　　» 每个Server启动以后都询问其它的Server它要投票给谁。<br>　　» 对于其他server的询问，server每次根据自己的状态都回复自己推荐的leader的id和上一次处理事务的zxid（系统启动时每个server都会推荐自己）<br>　　» 收到所有Server回复以后，就计算出zxid最大的哪个Server，并将这个Server相关信息设置成下一次要投票的Server。<br>　　» 计算这过程中获得票数最多的的sever为获胜者，如果获胜者的票数超过半数，则改server被选为leader。否则，继续这个过程，直到leader被选举出来　　</p>
<p>　　» leader就会开始等待server连接<br>　　» Follower连接leader，将最大的zxid发送给leader<br>　　» Leader根据follower的zxid确定同步点<br>　　» 完成同步后通知follower 已经成为uptodate状态<br>　　» Follower收到uptodate消息后，又可以重新接受client的请求进行服务了</p>
<ol start="6">
<li><p>zk内存数据库</p>
</li>
<li><p>zk节点（node） 本身携带数据</p>
</li>
<li><p>zk怎么保证数据强一致性<br>据说Paxos算法的难理解与算法的知名度一样令人敬仰，所以我们先看如何保持数据的一致性，这里有个原则就是：<br>　　• 在一个分布式数据库系统中，如果各节点的初始状态一致，每个节点都执行相同的操作序列，那么他们最后能得到一个一致的状态。<br>　　• Paxos算法解决的什么问题呢，解决的就是保证每个节点执行相同的操作序列。好吧，这还不简单，master维护一个<br>　　   全局写队列，所有写操作都必须 放入这个队列编号，那么无论我们写多少个节点，只要写操作是按编号来的，就能保证一<br>　　　致性。没错，就是这样，可是如果master挂了呢。<br>　　• Paxos算法通过投票来对写操作进行全局编号，同一时刻，只有一个写操作被批准，同时并发的写操作要去争取选票，<br>　　　只有获得过半数选票的写操作才会被 批准（所以永远只会有一个写操作得到批准），其他的写操作竞争失败只好再发起一<br>　　　轮投票，就这样，在日复一日年复一年的投票中，所有写操作都被严格编号排 序。编号严格递增，当一个节点接受了一个<br>　　　编号为100的写操作，之后又接受到编号为99的写操作（因为网络延迟等很多不可预见原因），它马上能意识到自己 数据<br>　　　不一致了，自动停止对外服务并重启同步过程。任何一个节点挂掉都不会影响整个集群的数据一致性（总2n+1台，除非挂掉大于n台）。<br>　 总结<br>　　• Zookeeper 作为 Hadoop 项目中的一个子项目，是 Hadoop 集群管理的一个必不可少的模块，它主要用来控制集群中的数据，</p>
</li>
</ol>
<p>　　　如它管理 Hadoop 集群中的 NameNode，还有 Hbase 中 Master Election、Server 之间状态同步等<br>Paxos(派克寿司)算法就是用来解决这类问题，多台服务器通过内部投票表决机制决定一个数据的更新与写入</p>
<ol start="9">
<li><p>一致性级别划分<br>强一致性<br>顺序一致性<br>弱一致性（最终一致性）</p>
</li>
<li><p>cap原理<br>c一致性<br>a可用性<br>p分区容错性<br>节点多了会导致写数据延时变大，因为更多的节点需要同步<br>节点多了Leader选举耗时变长，从而会放大网络的问题， 可以通过引入 observer（不参与选举）节点缓解这个问题.</p>
</li>
</ol>
<p>base理论<br>ba基本可用<br>s 柔韧性<br>e 最终一致性<br>原子性和持久性必须从根本上保障，为了可用性、性能和服务降级的需要，只有降低一致性和隔离性的要求。</p>
<ol start="11">
<li><p>zk数据模型</p>
</li>
<li><p>层次化的目录结构</p>
</li>
<li><p>唯一路径表示</p>
</li>
<li><p>节点包含数据和子节点，临时数据不包含子节点</p>
</li>
<li><p>数据解读</p>
</li>
</ol>
<p>cZxid = 0x89  创建的事物ID<br>ctime = Mon Aug 10 00:26:27 CST 2020 创建时间<br>mZxid = 0x89 修改的事物ID<br>mtime = Mon Aug 10 00:26:27 CST 2020 修改时间<br>pZxid = 0x89 该节点的子节点列表最后一次修改时的事务id，只有子节点列表变更才会更新pZxid，子节点内容变更不会更新<br>cversion = 0 子节点版本号，当前节点的子节点每次变化时值增加1<br>dataVersion = 0 数据节点内容版本号，节点创建时为0，每更新一次节点内容(不管内容有无变化)该版本号的值增加1<br>aclVersion = 0 节点的ACL版本号，表示该节点ACL信息变更次数<br>ephemeralOwner = 0x100de2956c70006  创建该临时节点的会话的sessionId；如果当前节点为持久节点，则ephemeralOwner=0<br>dataLength = 2 数据节点内容长度<br>numChildren = 0 当前节点的子节点个数</p>
<p>13.为什么zookeeper集群的数目，一般为奇数个</p>
<p>•Leader选举算法采用了Paxos协议；<br>Paxos核心思想：当多数Server写成功，则任务数据写成功如果有3个Server，则两个写成功即可；如果有4或5个Server，则三个写成功即可。<br>Server数目一般为奇数（3、5、7）如果有3个Server，则最多允许1个Server挂掉；如果有4个Server，则同样最多允许1个Server挂掉由此，</p>
<p>我们看出3台服务器和4台服务器的的容灾能力是一样的，所以为了节省服务器资源，一般我们采用奇数个数，作为服务器部署个数。</p>
<ol start="14">
<li>Observer　　</li>
</ol>
<p>　　• Zookeeper需保证高可用和强一致性；<br>　　• 为了支持更多的客户端，需要增加更多Server；<br>　　• Server增多，投票阶段延迟增大，影响性能；<br>　　• 权衡伸缩性和高吞吐率，引入Observer<br>　　• Observer不参与投票；<br>　　• Observers接受客户端的连接，并将写请求转发给leader节点；<br>　　• 加入更多Observer节点，提高伸缩性，同时不影响吞吐率</p>
<ol start="15">
<li>分布式锁<br>访问的时候会创建带顺序号的临时/短暂(EPHEMERAL_SEQUENTIAL)节点，<br>比如，系统A创建了id_000000节点，系统B创建了id_000002节点，系统C创建了id_000001节点。<br>接着，拿到/locks节点下的所有子节点(id_000000,id_000001,id_000002)，判断自己创建的是不是最小的那个节点</li>
</ol>
<p>如果是，则拿到锁。</p>
<p>释放锁：执行完操作后，把创建的节点给删掉</p>
<p>如果不是，则监听比自己要小1的节点变化<br>原理：</p>
<p>系统A拿到/locks节点下的所有子节点，经过比较，发现自己(id_000000)，是所有子节点最小的。所以得到锁</p>
<p>系统B拿到/locks节点下的所有子节点，经过比较，发现自己(id_000002)，不是所有子节点最小的。所以监听比自己小1的节点id_000001的状态</p>
<p>系统C拿到/locks节点下的所有子节点，经过比较，发现自己(id_000001)，不是所有子节点最小的。所以监听比自己小1的节点id_000000的状态……等到系统A执行完操作以后，将自己创建的节点删除(id_000000)。通过监听，系统C发现id_000000节点已经删除了，发现自己已经是最小的节点了，于是顺利拿到锁….</p>
<ol start="16">
<li>ZooKeeper的ZAB算法与Paxos的本质区别</li>
</ol>
<p>Zab 协议分为三大块：</p>
<ul>
<li>广播（boardcast）：Zab 协议中，所有的写请求都由 leader 来处理。正常工作状态下，leader 接收请求并通过广播协议来处理。</li>
<li>恢复（recovery）：当服务初次启动，或者 leader 节点挂了，系统就会进入恢复模式，直到选出了有合法数量 follower 的新 leader，<br>然后新 leader 负责将整个系统同步到最新状态。</li>
<li>选举（Election）：Zab通过消息版本号选举出Leader来负责所在区域的写入工作<br>选举：<br>成为 leader 的条件<br>选epoch最大的<br>epoch相等，选 zxid 最大的<br>epoch和zxid都相等，选择server id最大的（就是我们配置data目录下的myid）<br>节点在选举开始都默认投票给自己，当接收其他节点的选票时，会根据上面的条件更改自己的选票并重新发送选票给其他节点，当有一个节点的得票超过半数，<br>该节点会设置自己的状态为 leading，其他节点会设置自己的状态为 following。<br>恢复：<br>这一阶段 follower 发送它们的 lastZixd 给 leader，leader 根据 lastZixd 决定如何同步数据。这里的实现跟前面 Phase 2 有所不同：<br>Follower 收到 TRUNC 指令会中止 L.lastCommittedZxid 之后的提议，收到 DIFF 指令会接收新的提议。<br>广播：<br>广播的过程实际上是一个简化的二阶段提交过程：</li>
</ul>
<ol>
<li>Leader 接收到消息请求后，将消息赋予一个全局唯一的 64 位自增 id，叫做：zxid，通过 zxid 的大小比较即可实现因果有序这一特性。</li>
<li>Leader 通过先进先出队列（通过 TCP 协议来实现，以此实现了全局有序这一特性）将带有 zxid 的消息作为一个提案（proposal）分发给所有 follower。</li>
<li>当 follower 接收到 proposal，先将 proposal 写到硬盘，写硬盘成功后再向 leader 回一个 ACK。</li>
<li>当 leader 接收到合法数量的 ACKs 后，leader 就向所有 follower 发送 COMMIT 命令，同事会在本地执行该消息。</li>
<li>当 follower 收到消息的 COMMIT 命令时，就会执行该消息</li>
</ol>
<p>什么是脑裂</p>
<p>zookeeper集群中存在多个leader</p>
<p>zab协议怎么解决脑裂<br>选举leader要求支持过半,也叫快速选举法,不需要等所有的flower进行投票选举</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/06/zookeeper/" data-id="ckgtnonol000zm8ul2p1zemkz" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/blog/2020/07/19/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          双亲委派
        
      </div>
    </a>
  
  
    <a href="/blog/2020/06/12/gradle%E7%9F%A5%E8%AF%86/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">gradle知识</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/10/">October 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/08/">August 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/07/">July 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/06/">June 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/05/">May 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/04/">April 2020</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/blog/2020/10/25/%E6%AF%8F%E6%97%A5%E5%AD%A6%E4%B9%A0/">每日学习</a>
          </li>
        
          <li>
            <a href="/blog/2020/10/12/mybatis-plus/">mybatis-plus</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/30/%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F/">秒杀系统</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/29/elasticsearch%E7%9F%A5%E8%AF%86/">elasticsearch知识</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/28/redis%E9%9D%A2%E8%AF%95/">redis面试</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2020 yanglf007<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/blog/" class="mobile-nav-link">Home</a>
  
    <a href="/blog/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/blog/fancybox/jquery.fancybox.css">

  
<script src="/blog/fancybox/jquery.fancybox.pack.js"></script>




<script src="/blog/js/script.js"></script>




  </div>
</body>
</html>